﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using System.IO.Ports;
using System.Threading.Tasks;
using Modbus.Device;

namespace HenhouseEnvironmentCtrl
{
    public partial class ChartDataForm : Form
    {
        private System.Threading.Timer timer;
        private IModbusSerialMaster master;
        private SerialPort port;
        private int currentSlaveId = 1;

        private const int MaxDataPoints = 15;
        private Queue<CurrentData> temperatureData = new Queue<CurrentData>();
        private Queue<CurrentData> humidityData = new Queue<CurrentData>();
        private Queue<CurrentData> pm25Data = new Queue<CurrentData>();
        private Queue<CurrentData> nh3Data = new Queue<CurrentData>();
        private Queue<CurrentData> co2Data = new Queue<CurrentData>();

        public ChartDataForm(IModbusSerialMaster master, SerialPort port)
        {
            InitializeComponent();
            this.master = master;
            this.port = port;
        }

        private void ChartDataForm_Load(object sender, EventArgs e)
        {
            timer = new System.Threading.Timer(TimerCallback, null, 0, 1000);

            chartTempHumidity.ChartAreas[0].AxisX.LabelStyle.Format = "HH:mm:ss";
            chartOtherData.ChartAreas[0].AxisX.LabelStyle.Format = "HH:mm:ss";

            AddSeries(chartTempHumidity, "温度");
            AddSeries(chartTempHumidity, "湿度");
            AddSeries(chartOtherData, "PM2.5");
            AddSeries(chartOtherData, "NH3");
            AddSeries(chartOtherData, "CO2");

            cboSlave.Items.Add("从站1");
            cboSlave.Items.Add("从站2");
            cboSlave.Items.Add("从站3");
            cboSlave.SelectedIndex = 0;
            cboSlave.SelectedIndexChanged += CboSlave_SelectedIndexChanged;
        }

        private void TimerCallback(object state)
        {
            try
            {
                if (master != null && port != null && port.IsOpen)
                {
                    ushort[] data = master.ReadHoldingRegisters((byte)currentSlaveId, 0, 5);
                    float temperature = data[0] / 10.0f;
                    float humidity = data[1] / 10.0f;
                    int pm25 = data[2];
                    int nh3 = data[3];
                    float co2 = data[4] / 10.0f;

                    DateTime now = DateTime.Now;

                    EnqueueData(temperatureData, new CurrentData(now, Math.Round(temperature, 1)));
                    EnqueueData(humidityData, new CurrentData(now, Math.Round(humidity, 1)));
                    EnqueueData(pm25Data, new CurrentData(now, pm25));
                    EnqueueData(nh3Data, new CurrentData(now, nh3));
                    EnqueueData(co2Data, new CurrentData(now, Math.Round(co2, 1)));

                    this.Invoke(new Action(() =>
                    {
                        if (!this.IsDisposed)
                        {
                            BindDataToChart(chartTempHumidity, "温度", temperatureData);
                            BindDataToChart(chartTempHumidity, "湿度", humidityData);
                            BindDataToChart(chartOtherData, "PM2.5", pm25Data);
                            BindDataToChart(chartOtherData, "NH3", nh3Data);
                            BindDataToChart(chartOtherData, "CO2", co2Data);
                        }
                    }));
                }
            }
            catch (Exception ex)
            {
                this.Invoke(new Action(() =>
                {
                    if (!this.IsDisposed)
                    {
                        MessageBox.Show($"读取数据失败: {ex.Message}");
                    }
                }));
            }
        }

        private void EnqueueData(Queue<CurrentData> queue, CurrentData data)
        {
            if (queue.Count >= MaxDataPoints)
            {
                queue.Dequeue();
            }
            queue.Enqueue(data);
        }

        private void BindDataToChart(Chart chart, string seriesName, Queue<CurrentData> dataQueue)
        {
            chart.Series[seriesName].Points.DataBind(dataQueue, "CurrentDateTime", "Data", "");
        }

        private void AddSeries(Chart chart, string legendText)
        {
            Series series = new Series
            {
                Name = legendText,
                ChartArea = chart.ChartAreas[0].Name,
                ChartType = SeriesChartType.Spline,
                Legend = chart.Legends[0].Name,
                LegendText = legendText,
                Label = "#VAL",
                XValueType = ChartValueType.DateTime,
                YValueType = ChartValueType.Double,
                BorderWidth = 2
            };
            chart.Series.Add(series);
        }

        private void CboSlave_SelectedIndexChanged(object sender, EventArgs e)
        {
            currentSlaveId = cboSlave.SelectedIndex + 1;
            ClearData();
        }

        private void ClearData()
        {
            temperatureData.Clear();
            humidityData.Clear();
            pm25Data.Clear();
            nh3Data.Clear();
            co2Data.Clear();
        }

        private void BtnBack_Click(object sender, EventArgs e)
        {
            timer.Dispose();
            this.Close();
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);
            timer.Dispose();
        }
    }

    public class CurrentData
    {
        public DateTime CurrentDateTime { get; set; }
        public double Data { get; set; }

        public CurrentData(DateTime dateTime, double data)
        {
            CurrentDateTime = dateTime;
            Data = data;
        }
    }
}
